package org.jeecg.modules.xxgx.fpht.eventListener;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.config.TenantContext;
import org.jeecg.modules.xxgx.djgl.entity.*;
import org.jeecg.modules.xxgx.djgl.service.*;
import org.jeecg.modules.xxgx.fpgl.entity.CsXxFpxx;
import org.jeecg.modules.xxgx.fpgl.entity.CsXxFpxxmx;
import org.jeecg.modules.xxgx.fpgl.service.ICsXxFpxxService;
import org.jeecg.modules.xxgx.fpgl.service.ICsXxFpxxmxService;
import org.jeecg.modules.xxgx.fpht.dto.DjhtDjmxDto;
import org.jeecg.modules.xxgx.fpht.dto.DjhtDto;
import org.jeecg.modules.xxgx.fpht.dto.DjhtFpmxDto;
import org.jeecg.modules.xxgx.fpht.dto.DjhtResultDto;
import org.jeecg.modules.xxgx.fpht.entity.CsXxHtqqxxDo;
import org.jeecg.modules.xxgx.fpht.entity.CsXxJkpz;
import org.jeecg.modules.xxgx.fpht.event.FphtEvent;
import org.jeecg.modules.xxgx.fpht.service.ICsXxHtqqxxService;
import org.jeecg.modules.xxgx.fpht.service.ICsXxJkpzService;
import org.jeecg.modules.xxgx.fpht.util.DateUtil;
import org.jeecg.modules.xxgx.fpht.util.HttpClientUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
public class FphtEventListener {

    @Autowired
    private ICsXxYkdjService iCsXxYkdjService1;

    @Autowired
    private ICsXxYkdjmxService iCsXxYkdjmxService1;

    @Autowired
    private ICsXxFpxxService iCsXxFpxxService1;

    @Autowired
    private ICsXxFpxxmxService iCsXxFpxxmxService1;

    @Autowired
    private ICsXxJkpzService iCsXxJkpzService;

    @Autowired
    private ICsXxHtqqxxService iCsXxHtqqxxService;

    @Autowired
    private ICsXxDjclmxService iCsXxDjclmxService;

    @Autowired
    private ICsXxDkdjmxService iCsXxDkdjmxService;

    @Autowired
    private ICsXxDkdjService iCsXxDkdjService;

    @Async
    @EventListener
    public void handle(FphtEvent event) {
        String id = (String) event.getSource();
        //这个id  是待开单据（cs_xx_dkdj）  已开单据（cs_xx_ykdj）的 主键
        //同时也是 销项发票（cs_xx_fpxx） 表的djbh字段值

        //已开单据主表信息
        CsXxYkdj ykdj = iCsXxYkdjService1.getById(id);

        if (ykdj == null) return;

        //只有是推送单据后开票成功的  才需要回填
        if (!"djkp".equals(ykdj.getSjlx())) return;

        //已开单据明细表信息
        List<CsXxYkdjmx> ykdjmxlist = iCsXxYkdjmxService1.lambdaQuery().eq(CsXxYkdjmx::getFromid, id).list();

        //发票信息主表信息
        CsXxFpxx fpxx = iCsXxFpxxService1.lambdaQuery().eq(CsXxFpxx::getDjbh, id).one();

        //发票信息明细表信息
        List<CsXxFpxxmx> fpxxlist = iCsXxFpxxmxService1.lambdaQuery().eq(CsXxFpxxmx::getFromid, fpxx.getId()).list();

        //根据  数据来源  单据类型  查询回填的地址
        LambdaQueryWrapper<CsXxJkpz> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotEmpty(ykdj.getSjlx()), CsXxJkpz::getSjlx, ykdj.getSjlx());//数据类型
        queryWrapper.eq(StringUtils.isNotEmpty(ykdj.getSjly()), CsXxJkpz::getSjly, ykdj.getSjly());//数据来源
        queryWrapper.eq(CsXxJkpz::getJklx, "fpht");//发票回填接口类型
        CsXxJkpz jkpz = iCsXxJkpzService.getOne(queryWrapper, false);
        if (jkpz != null) {
            switch (jkpz.getDjfs()) {
                case "http":
                    log.info("http回填");
                    doHttpHt(jkpz.getDjdz(), ykdj, ykdjmxlist, fpxx, fpxxlist);
                    break;
                case "mysql":
                    log.info("mysql回填");
                    break;
                case "sqlserver":
                    log.info("sqlserver回填");
                    break;
                case "oracle":
                    log.info("oracle回填");
                    break;
                default:
                    log.info("未查询到需要回填的配置信息");
            }
        }
    }

    public void doHttpHt(String url, CsXxYkdj ykdj, List<CsXxYkdjmx> ykdjmxlist, CsXxFpxx fpxx, List<CsXxFpxxmx> fpxxmxlist) {
        TenantContext.setTenant(Convert.toStr(ykdj.getTenantId()));
        log.info("开始准备回填,回填地址:" + url);
        DjhtDto dto = new DjhtDto();
        List<String> ywdjbhlist = new ArrayList<>();
        //判断当前这个单据是否经历过拆分或者合并 如果有 则找到相对应的ywdjbh
        //如果是合并后的单据 开票成功 那ywdjbh这个数组就要返回多个ywdjbh 因为是合并 所以是多个单据对应一个发票
        //首先判断当前的单据是否经历过拆分或者合并
        String clfs = ykdj.getClfs();
        if ("0".equals(clfs)) {
            //没有经历过拆分或者合并处理
            ywdjbhlist.add(ykdj.getYwdjbh());

            //处理ywdjxx
            List<DjhtDjmxDto> djmxlist = new ArrayList<>();
            DjhtDjmxDto djmx = new DjhtDjmxDto();
            djmx.setYwdjbh(ykdj.getYwdjbh());
            djmx.setKhmc(ykdj.getKhmc());
            djmx.setKhsh(ykdj.getKhsh());
            djmx.setHjje(ykdj.getHjje());
            djmx.setHjse(ykdj.getHjse());
            djmx.setJshj(ykdj.getHjje().add(ykdj.getHjse()));
            djmxlist.add(djmx);
            dto.setYwdjxx(djmxlist);

            //处理单据明细
            List<DjhtFpmxDto> fpmx = new ArrayList<>();
            for (CsXxFpxxmx csXxFpxxmx1 : fpxxmxlist) {
                DjhtFpmxDto djhtFpmxDto = new DjhtFpmxDto();
                BeanUtils.copyProperties(csXxFpxxmx1, djhtFpmxDto);
                djhtFpmxDto.setYwdjbh(ykdj.getYwdjbh());
                fpmx.add(djhtFpmxDto);
            }
            dto.setFpmx(fpmx);
        } else {
            //经历过合并/拆分处理
            //1.在单据处理表中  查询原 单据主键
            List<String> xdjzj = ykdjmxlist.stream().map(CsXxYkdjmx::getId).collect(Collectors.toList());
            List<CsXxDjclmxDo> ydjlist = iCsXxDjclmxService.lambdaQuery().in(CsXxDjclmxDo::getXdjzj, xdjzj).list();
            List<String> ydjzj = ydjlist.stream().map(CsXxDjclmxDo::getYdjzj).collect(Collectors.toList());
            //2.根据原单据主键  查询原来的ywdjbh
            List<CsXxDkdjmx> dkdjmxlist = iCsXxDkdjmxService.lambdaQuery().in(CsXxDkdjmx::getId, ydjzj).list();
            ywdjbhlist = dkdjmxlist.stream().map(CsXxDkdjmx::getYwdjbh).distinct().collect(Collectors.toList());
            //处理ywdjxx
            //根据dkdjmxlist 可以知道 对应的 原单据的 formid
            List<String> yformids = dkdjmxlist.stream().map(CsXxDkdjmx::getFromid).collect(Collectors.toList());
            //根据原formid 可以查出来原来的 dkdj
            List<CsXxDkdj> ydkdjlist = iCsXxDkdjService.lambdaQuery().in(CsXxDkdj::getId, yformids).list();
            List<DjhtDjmxDto> djmxlist = new ArrayList<>();
            for (String ywdjbh : ywdjbhlist) {
                BigDecimal hjje = ydkdjlist.stream().filter(i -> ywdjbh.equals(i.getYwdjbh())).collect(Collectors.toList()).stream().map(CsXxDkdj::getHjje).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal hjse = ydkdjlist.stream().filter(i -> ywdjbh.equals(i.getYwdjbh())).collect(Collectors.toList()).stream().map(CsXxDkdj::getHjse).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal jshj = hjje.add(hjse);
                DjhtDjmxDto djmx = new DjhtDjmxDto();
                djmx.setYwdjbh(ywdjbh);
                djmx.setKhmc(ykdj.getKhmc());
                djmx.setKhsh(ykdj.getKhsh());
                djmx.setHjje(hjje);
                djmx.setHjse(hjse);
                djmx.setJshj(jshj);
                djmxlist.add(djmx);
            }
            dto.setYwdjxx(djmxlist);
            //处理单据明细
            List<DjhtFpmxDto> fpmx1 = new ArrayList<>();
            for (int i = 0; i < ykdjmxlist.size(); i++) {
                CsXxYkdjmx csXxYkdjmx = ykdjmxlist.get(i);
                DjhtFpmxDto djhtFpmxDto = new DjhtFpmxDto();
                BeanUtils.copyProperties(csXxYkdjmx,djhtFpmxDto);
                fpmx1.add(djhtFpmxDto);
            }
            dto.setFpmx(fpmx1);
        }
        String[] ywdjbh = ywdjbhlist.toArray(new String[ywdjbhlist.size()]);
        dto.setYwdjbh(ywdjbh);
        dto.setFplxdm(ykdj.getFplxdm());
        dto.setKplx(ykdj.getKplx());
        dto.setFpdm(fpxx.getFpdm());
        dto.setFphm(fpxx.getFphm());
        dto.setSjly(ykdj.getSjly());
        dto.setDjlx(ykdj.getDjlx());
        dto.setSjlx(ykdj.getSjlx());
        String kprq = DateUtil.getFormatDate(fpxx.getKprq(), "yyyy-MM-dd HH:mm:ss");
        dto.setKprq(kprq);
        dto.setYfphm(fpxx.getYfphm());
        dto.setYfpdm(fpxx.getYfpdm());
        dto.setHjje(Convert.toStr(fpxx.getHjje()));
        dto.setHjse(Convert.toStr(fpxx.getHjse()));
        dto.setJshj(Convert.toStr(fpxx.getHjje().add(fpxx.getHjse())));
        dto.setSkm(fpxx.getSkm());
        dto.setJym(fpxx.getJym());
        dto.setEwm(fpxx.getEwm());
        dto.setKpr(ykdj.getKpr());
        log.info("回填内容:" + JSONObject.toJSONString(dto));

        CsXxHtqqxxDo csXxHtqqxxDo = new CsXxHtqqxxDo();
        String id = IdWorker.getIdStr();
        csXxHtqqxxDo.setId(id);
        csXxHtqqxxDo.setTenantId(Convert.toStr(ykdj.getTenantId()));
        csXxHtqqxxDo.setCompanyId(ykdj.getCompanyId());
        csXxHtqqxxDo.setSysOrgCode(ykdj.getSysOrgCode());
        csXxHtqqxxDo.setYwdjbh(ykdj.getYwdjbh());
        csXxHtqqxxDo.setFpdm(fpxx.getFpdm());
        csXxHtqqxxDo.setFphm(fpxx.getFphm());
        csXxHtqqxxDo.setSjly(ykdj.getSjly());
        csXxHtqqxxDo.setDjlx(ykdj.getDjlx());
        csXxHtqqxxDo.setSjlx(ykdj.getSjlx());
        csXxHtqqxxDo.setKplx(ykdj.getKplx());
        csXxHtqqxxDo.setKprq(DateUtil.getFormatDate(ykdj.getKprq()));
        csXxHtqqxxDo.setUrl(url);
        csXxHtqqxxDo.setContent(JSONObject.toJSONString(dto));
        csXxHtqqxxDo.setHtrq(new Date());

        //保存请求发送记录
        iCsXxHtqqxxService.save(csXxHtqqxxDo);

        //发送回填请求
        try {
            String result = HttpClientUtil.doPostJson(url, JSONObject.toJSONString(dto));
            log.info("发票回填返回结果:" + result);
            DjhtResultDto djhtResultDto = JSON.parseObject(result, DjhtResultDto.class);
            if ("200".equals(djhtResultDto.getCode())) {
                CsXxHtqqxxDo csXxHtqqxxDo1 = new CsXxHtqqxxDo();
                csXxHtqqxxDo1.setId(id);
                csXxHtqqxxDo1.setXyzt("0");
                csXxHtqqxxDo1.setXynr(djhtResultDto.getMessage());
                iCsXxHtqqxxService.updateById(csXxHtqqxxDo1);
            } else {
                CsXxHtqqxxDo csXxHtqqxxDo1 = new CsXxHtqqxxDo();
                csXxHtqqxxDo1.setId(id);
                csXxHtqqxxDo1.setXyzt("1");
                csXxHtqqxxDo1.setXynr(djhtResultDto.getMessage());
                iCsXxHtqqxxService.updateById(csXxHtqqxxDo1);
            }
        } catch (Exception e) {
            CsXxHtqqxxDo csXxHtqqxxDo1 = new CsXxHtqqxxDo();
            csXxHtqqxxDo1.setId(id);
            csXxHtqqxxDo1.setXyzt("1");
            csXxHtqqxxDo1.setXynr(e.getMessage());
            iCsXxHtqqxxService.updateById(csXxHtqqxxDo1);
        }

    }

}
